package com.mdd.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.mdd.common.BaseContext;
import com.mdd.common.CustomException;
import com.mdd.pojo.Blog;
import com.mdd.pojo.OrderDetail;
import com.mdd.pojo.Orders;
import com.mdd.pojo.User;
import com.mdd.pojo.request.BlogAddRequest;
import com.mdd.pojo.request.BlogQueryRequest;
import com.mdd.pojo.request.BlogReplyRequest;
import com.mdd.pojo.request.BlogUpdateRequest;
import com.mdd.pojo.vo.BlogVo;
import com.mdd.pojo.vo.UserVo;
import com.mdd.service.BlogService;
import com.mdd.mapper.BlogMapper;
import com.mdd.service.OrderDetailService;
import com.mdd.service.OrderService;
import com.mdd.service.UserService;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
* @author 21958
* @description 针对表【blog】的数据库操作Service实现
* @createDate 2023-04-29 20:51:52
*/
@Service
public class BlogServiceImpl extends ServiceImpl<BlogMapper, Blog>
    implements BlogService{

    @Autowired
    private UserService userService;

    @Autowired
    private OrderDetailService orderDetailService;

    @Autowired
    private OrderService orderService;

    @Autowired
    private StringRedisTemplate redisTemplate;

    /**
     * 删除评论
     * @param id
     * @return
     */
    @Override
    public boolean removeBlog(Long id) {
        //校验
        judgeNull(id);
        if (id<=0){
            throw new CustomException("请求参数有误");
        }
        //获取当前用户id
        Long currentId = BaseContext.getCurrentId();
        //删除评论
        LambdaQueryWrapper<Blog> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Blog::getId,id).eq(Blog::getUserId,currentId);
        boolean res = remove(queryWrapper);
        if (!res) throw new CustomException("删除失败");
        return true;
    }

    /**
     * 用户添加评论
     * @param blogAddRequest
     * @return
     */
    @Override
    public Long addBlog(BlogAddRequest blogAddRequest) {
        //校验
        judgeNull(blogAddRequest);
        //参数校验
        String content = blogAddRequest.getContent();
        if (StringUtils.isEmpty(content)) {
            throw new CustomException("内容不能为空");
        }
        Integer star = blogAddRequest.getStar();
        if (star==null||star<1){
            throw new CustomException("星级有误");
        }
        if (blogAddRequest.getOrderId() == null || blogAddRequest.getUserId() == null) {
            throw new CustomException("订单或用户id为空");
        }
        Long orderId = blogAddRequest.getOrderId();
        //订单是否存在
        Orders byId = orderService.getById(orderId);
        if (byId == null) {
            throw new CustomException("订单不存在");
        }
        //todo 查看当前订单的userId与当前用户是否一致
        // 检查当前用户是否评价过(一个订单只能评价一次)
        Long userId = blogAddRequest.getUserId();
        LambdaQueryWrapper<Blog> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Blog::getUserId,userId).eq(Blog::getOrderId,orderId );
        int count = count(queryWrapper);
        //如果大于1说明当前用户对该订单已评价过了
        if (count != 0) {
            throw new CustomException("您已评价过该订单");
        }
        //添加评论
        Blog blog = new Blog();
        BeanUtils.copyProperties(blogAddRequest,blog);
        boolean save = save(blog);
        if (!save) throw new CustomException("评价添加失败");
        return blog.getId();
    }

    /**
     * 用户修改评论
     * @param blogUpdateRequest
     * @return
     */
    @Override
    public boolean updateBlog(BlogUpdateRequest blogUpdateRequest) {
        //检验
        judgeNull(blogUpdateRequest);
        if (blogUpdateRequest.getId() <= 0) {
            throw new CustomException("请求参数有误");
        }
        if (blogUpdateRequest.getStar() != null && blogUpdateRequest.getStar() <= 0) {
            throw new CustomException("星级修改有误");
        }
        Blog blog = new Blog();
        BeanUtils.copyProperties(blogUpdateRequest,blog);
        boolean res = updateById(blog);
        if (!res) throw new CustomException("修改失败");
        return res;
    }

    /**
     * 获得评论列表
     * @param blogQueryRequest
     * @return
     */
    @Override
    public Page<BlogVo> blogList(BlogQueryRequest blogQueryRequest) {
        //检验
        judgeNull(blogQueryRequest);
        //构建条件
        Long id = blogQueryRequest.getId();
        Long userId = blogQueryRequest.getUserId();
        String content = blogQueryRequest.getContent();
        Integer star = blogQueryRequest.getStar();
        LambdaQueryWrapper<Blog> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(id!=null,Blog::getId,id)
                .eq(userId!=null,Blog::getUserId,userId)
                .like(content!=null,Blog::getContent,content)
                .eq(star!=null,Blog::getStar,star);
        Page<Blog> page = new Page<>(blogQueryRequest.getCurrent(), blogQueryRequest.getPageSize());
        //分页查询
        Page<Blog> blogPage = page(page, queryWrapper);
        //数据处理
        Page<BlogVo> blogVoPage = new Page<>();
        BeanUtils.copyProperties(blogPage,blogVoPage,"records");
        //对评论列表进行处理
        List<BlogVo> blogVoList = blogPage.getRecords().stream().map(blog -> {
            BlogVo blogVo = new BlogVo();
            BeanUtils.copyProperties(blog, blogVo);
            //查询用户信息
            User byId = userService.getById(blog.getUserId());
            //用户脱敏
            UserVo userVo = userService.getUserVo(byId);
            blogVo.setUser(userVo);
            //查询订单详细菜品信息
            LambdaQueryWrapper<OrderDetail> queryWrapper1 = new LambdaQueryWrapper<>();
            //查询该订单包含的菜品名信息
            queryWrapper1.eq(OrderDetail::getOrderId, blog.getOrderId()).select(OrderDetail::getName);
            List<OrderDetail> list = orderDetailService.list(queryWrapper1);
            //得到该订单的菜品信息
            List<String> collect = list.stream().map(OrderDetail::getName).collect(Collectors.toList());
            blogVo.setOrderDetails(collect);
            //设置评论的isLiked
            isLiked(blogVo);
            //设置评论的点赞top
            setLikeTop(blogVo);
            return blogVo;
        }).collect(Collectors.toList());
        blogVoPage.setRecords(blogVoList);
        return blogVoPage;
    }

    /**
     * 点赞评论
     * @param blogId
     * @return
     */
    @Override
    public boolean userLikeBlog(Long blogId) {
        //校验
        if (blogId <= 0) {
            throw new CustomException("请求参数有误");
        }
        //在redis中查询当前用户是否对该评论点过赞
        String key = "blog:likes:"+blogId;
        Long currentId = BaseContext.getCurrentId();
        ZSetOperations<String, String> opsForZSet = redisTemplate.opsForZSet();
        Double score = opsForZSet.score(key, currentId.toString());
        //判断是否点过赞对该评论
        boolean res;
        if (score == null) {
            //则说明没有点过赞
            //对该评论点赞
            res = update().setSql("liked=liked+1").eq("id", blogId).update();
            if (res) {
                //存入到redis中
                opsForZSet.add(key,currentId.toString(), System.currentTimeMillis());
            }
        }else {
            //取消点赞
            res = update().setSql("liked=liked-1").eq("id", blogId).update();
            if (res) {
                //存入到redis中
                opsForZSet.remove(key,currentId.toString());
            }
        }
        return res;
    }

    /**
     * 商家回复
     * @param blogReplyRequest
     * @return
     */
    @Override
    public boolean replyBlog(BlogReplyRequest blogReplyRequest) {
        //校验
        if (StringUtils.isEmpty(blogReplyRequest.getReply())) {
            throw new CustomException("回复不能为空");
        }
        if (blogReplyRequest.getId() == null || blogReplyRequest.getId() <= 0) {
            throw new CustomException("请求参数有误");
        }

        //回复评价
        LambdaUpdateWrapper<Blog> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.set(Blog::getReply,blogReplyRequest.getReply());
        updateWrapper.eq(Blog::getId,blogReplyRequest.getId());
        boolean update = update(updateWrapper);
        //返回结果
        if (!update) {
            throw new CustomException("回复失败");
        }
        return true;
    }

    /**
     *设置isLiked
     * @param blog
     */
    public void isLiked(BlogVo blog){
        String key = "blog:likes:"+blog.getId();
        //获取当前用户id
        Long userId = BaseContext.getCurrentId();
        //判断当前用户是否点赞该评论
        ZSetOperations<String, String> zSetOperations = redisTemplate.opsForZSet();
        Double score = zSetOperations.score(key, userId.toString());
        blog.setIsLiked(score!=null);
    }

    /**
     * 设置当前评论的点赞前五名的用户名
     * @param blogVo
     */
    public void setLikeTop(BlogVo blogVo){
        //获取key
        String key = "blog:likes:"+blogVo.getId();
        //从redis中获取当前评论的点赞top5
        ZSetOperations<String, String> zSetOperations = redisTemplate.opsForZSet();
        Set<String> range = zSetOperations.range(key, 0, 4);
        if (range == null) {
            return;
        }
        List<String> names = range.stream().map(id -> {
            long i = Long.parseLong(id);
            User byId = userService.getById(i);
            return byId.getName();
        }).collect(Collectors.toList());
        blogVo.setLikeTop(names);
    }

    public void judgeNull(Object params){
        if (params == null) {
            throw new CustomException("请求参数为空");
        }
    }
}




